Skip to main content
Version: Next

Telco Churn

Package Imports

!pip install xplainable
!pip install xplainable-client
Out:

Requirement already satisfied: xplainable in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (1.3.0)

Requirement already satisfied: xplainable-client>=1.3.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (1.3.0)

Requirement already satisfied: hyperopt>=0.2.7 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (0.2.7)

Requirement already satisfied: numba>=0.57.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (0.60.0)

Requirement already satisfied: numpy>=2.0.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (2.0.2)

Requirement already satisfied: pandas>=2.2.3 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (2.3.0)

Requirement already satisfied: pyperclip>=1.8.2 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (1.9.0)

Requirement already satisfied: scikit-learn>=1.3.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (1.7.0)

Requirement already satisfied: scipy>=1.6.2 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (1.15.3)

Requirement already satisfied: urllib3>=1.26.5 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (2.4.0)

Requirement already satisfied: psutil>=5.9.4 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (7.0.0)

Requirement already satisfied: joblib>=1.2.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (1.5.1)

Requirement already satisfied: networkx>=2.8.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (3.4.2)

Requirement already satisfied: tqdm>=4.62.3 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (4.67.1)

Requirement already satisfied: ipython in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (8.37.0)

Requirement already satisfied: packaging in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (25.0)

Requirement already satisfied: requests in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable) (2.32.4)

Requirement already satisfied: six in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from hyperopt>=0.2.7->xplainable) (1.17.0)

Requirement already satisfied: future in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from hyperopt>=0.2.7->xplainable) (1.0.0)

Requirement already satisfied: cloudpickle in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from hyperopt>=0.2.7->xplainable) (3.1.1)

Requirement already satisfied: py4j in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from hyperopt>=0.2.7->xplainable) (0.10.9.9)

Requirement already satisfied: llvmlite<0.44,>=0.43.0dev0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from numba>=0.57.0->xplainable) (0.43.0)

Requirement already satisfied: python-dateutil>=2.8.2 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from pandas>=2.2.3->xplainable) (2.9.0.post0)

Requirement already satisfied: pytz>=2020.1 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from pandas>=2.2.3->xplainable) (2025.2)

Requirement already satisfied: tzdata>=2022.7 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from pandas>=2.2.3->xplainable) (2025.2)

Requirement already satisfied: threadpoolctl>=3.1.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from scikit-learn>=1.3.0->xplainable) (3.6.0)

Requirement already satisfied: setuptools>=65.5.1 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client>=1.3.0->xplainable) (80.9.0)

Requirement already satisfied: decorator in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (5.2.1)

Requirement already satisfied: exceptiongroup in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (1.3.0)

Requirement already satisfied: jedi>=0.16 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (0.19.2)

Requirement already satisfied: matplotlib-inline in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (0.1.7)

Requirement already satisfied: pexpect>4.3 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (4.9.0)

Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (3.0.51)

Requirement already satisfied: pygments>=2.4.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (2.19.1)

Requirement already satisfied: stack_data in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (0.6.3)

Requirement already satisfied: traitlets>=5.13.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (5.14.3)

Requirement already satisfied: typing_extensions>=4.6 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable) (4.14.0)

Requirement already satisfied: wcwidth in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython->xplainable) (0.2.13)

Requirement already satisfied: parso<0.9.0,>=0.8.4 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from jedi>=0.16->ipython->xplainable) (0.8.4)

Requirement already satisfied: ptyprocess>=0.5 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from pexpect>4.3->ipython->xplainable) (0.7.0)

Requirement already satisfied: charset_normalizer<4,>=2 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from requests->xplainable) (3.4.2)

Requirement already satisfied: idna<4,>=2.5 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from requests->xplainable) (3.10)

Requirement already satisfied: certifi>=2017.4.17 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from requests->xplainable) (2025.6.15)

Requirement already satisfied: executing>=1.2.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from stack_data->ipython->xplainable) (2.2.0)

Requirement already satisfied: asttokens>=2.1.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from stack_data->ipython->xplainable) (3.0.0)

Requirement already satisfied: pure_eval in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from stack_data->ipython->xplainable) (0.2.3)

Requirement already satisfied: xplainable-client in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (1.3.0)

Requirement already satisfied: numpy>=2.0.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client) (2.0.2)

Requirement already satisfied: pandas>=2.2.3 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client) (2.3.0)

Requirement already satisfied: pyperclip in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client) (1.9.0)

Requirement already satisfied: Requests in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client) (2.32.4)

Requirement already satisfied: scikit_learn in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client) (1.7.0)

Requirement already satisfied: setuptools>=65.5.1 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client) (80.9.0)

Requirement already satisfied: urllib3 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client) (2.4.0)

Requirement already satisfied: xplainable in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable-client) (1.3.0)

Requirement already satisfied: python-dateutil>=2.8.2 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from pandas>=2.2.3->xplainable-client) (2.9.0.post0)

Requirement already satisfied: pytz>=2020.1 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from pandas>=2.2.3->xplainable-client) (2025.2)

Requirement already satisfied: tzdata>=2022.7 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from pandas>=2.2.3->xplainable-client) (2025.2)

Requirement already satisfied: six>=1.5 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from python-dateutil>=2.8.2->pandas>=2.2.3->xplainable-client) (1.17.0)

Requirement already satisfied: charset_normalizer<4,>=2 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from Requests->xplainable-client) (3.4.2)

Requirement already satisfied: idna<4,>=2.5 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from Requests->xplainable-client) (3.10)

Requirement already satisfied: certifi>=2017.4.17 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from Requests->xplainable-client) (2025.6.15)

Requirement already satisfied: scipy>=1.8.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from scikit_learn->xplainable-client) (1.15.3)

Requirement already satisfied: joblib>=1.2.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from scikit_learn->xplainable-client) (1.5.1)

Requirement already satisfied: threadpoolctl>=3.1.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from scikit_learn->xplainable-client) (3.6.0)

Requirement already satisfied: hyperopt>=0.2.7 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable->xplainable-client) (0.2.7)

Requirement already satisfied: numba>=0.57.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable->xplainable-client) (0.60.0)

Requirement already satisfied: psutil>=5.9.4 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable->xplainable-client) (7.0.0)

Requirement already satisfied: networkx>=2.8.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable->xplainable-client) (3.4.2)

Requirement already satisfied: tqdm>=4.62.3 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable->xplainable-client) (4.67.1)

Requirement already satisfied: ipython in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable->xplainable-client) (8.37.0)

Requirement already satisfied: packaging in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from xplainable->xplainable-client) (25.0)

Requirement already satisfied: future in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from hyperopt>=0.2.7->xplainable->xplainable-client) (1.0.0)

Requirement already satisfied: cloudpickle in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from hyperopt>=0.2.7->xplainable->xplainable-client) (3.1.1)

Requirement already satisfied: py4j in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from hyperopt>=0.2.7->xplainable->xplainable-client) (0.10.9.9)

Requirement already satisfied: llvmlite<0.44,>=0.43.0dev0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from numba>=0.57.0->xplainable->xplainable-client) (0.43.0)

Requirement already satisfied: decorator in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (5.2.1)

Requirement already satisfied: exceptiongroup in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (1.3.0)

Requirement already satisfied: jedi>=0.16 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (0.19.2)

Requirement already satisfied: matplotlib-inline in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (0.1.7)

Requirement already satisfied: pexpect>4.3 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (4.9.0)

Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (3.0.51)

Requirement already satisfied: pygments>=2.4.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (2.19.1)

Requirement already satisfied: stack_data in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (0.6.3)

Requirement already satisfied: traitlets>=5.13.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (5.14.3)

Requirement already satisfied: typing_extensions>=4.6 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from ipython->xplainable->xplainable-client) (4.14.0)

Requirement already satisfied: wcwidth in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->ipython->xplainable->xplainable-client) (0.2.13)

Requirement already satisfied: parso<0.9.0,>=0.8.4 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from jedi>=0.16->ipython->xplainable->xplainable-client) (0.8.4)

Requirement already satisfied: ptyprocess>=0.5 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from pexpect>4.3->ipython->xplainable->xplainable-client) (0.7.0)

Requirement already satisfied: executing>=1.2.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from stack_data->ipython->xplainable->xplainable-client) (2.2.0)

Requirement already satisfied: asttokens>=2.1.0 in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from stack_data->ipython->xplainable->xplainable-client) (3.0.0)

Requirement already satisfied: pure_eval in /Users/jtuppack/miniforge3/envs/xplainable-jupyter/lib/python3.10/site-packages (from stack_data->ipython->xplainable->xplainable-client) (0.2.3)

import pandas as pd
import xplainable as xp
from xplainable.core.models import XClassifier
from xplainable.core.optimisation.bayesian import XParamOptimiser
from xplainable.preprocessing.pipeline import XPipeline
from xplainable.preprocessing import transformers as xtf
from sklearn.model_selection import train_test_split
import requests

from xplainable_client.client.client import XplainableClient
from xplainable_client.client.base import XplainableAPIError
import json
xp.__version__
Out:

'1.3.1'

Instantiate Xplainable Cloud

Initialise the xplainable cloud using an API key from: https://platform.xplainable.io/

This allows you to save and collaborate on models, create deployments, create shareable reports.

# Initialize Xplainable Cloud client
client = XplainableClient(
api_key="f2ab664f-1325-4d8d-b55b-72c3c350dcab", #Create api key in xplainable cloud - https://platform.xplainable.io/
hostname="https://platform.xplainable.io"
)

Out:

Connected to Xplainable Cloud

User: jtupp

Hostname: https://platform.xplainable.io

API Key Expires: 2025-09-05T22:15:53.694866

Python Version: 3.10.18

Xplainable Version: 1.3.1

Read IBM Telco Churn Dataset

df = pd.read_csv('https://xplainable-public-storage.syd1.digitaloceanspaces.com/example_data/telco_customer_churn.csv')

Sample of the IBM Telco Churn Dataset

df.head()
CustomerIDCountCountryStateCityZip CodeLat LongLatitudeLongitudeGender...ContractPaperless BillingPayment MethodMonthly ChargesTotal ChargesChurn LabelChurn ValueChurn ScoreCLTVChurn Reason
03668-QPYBK1United StatesCaliforniaLos Angeles9000333.964131, -118.27278333.9641-118.273Male...Month-to-monthYesMailed check53.85108.15Yes1863239Competitor made better offer
19237-HQITU1United StatesCaliforniaLos Angeles9000534.059281, -118.3074234.0593-118.307Female...Month-to-monthYesElectronic check70.7151.65Yes1672701Moved
29305-CDSKC1United StatesCaliforniaLos Angeles9000634.048013, -118.29395334.048-118.294Female...Month-to-monthYesElectronic check99.65820.5Yes1865372Moved
37892-POOKP1United StatesCaliforniaLos Angeles9001034.062125, -118.31570934.0621-118.316Female...Month-to-monthYesElectronic check104.83046.05Yes1845003Moved
40280-XJGEX1United StatesCaliforniaLos Angeles9001534.039224, -118.26629334.0392-118.266Male...Month-to-monthYesBank transfer (automatic)103.75036.3Yes1895340Competitor had better devices

1. Data Preprocessing

Turn Label into Binary input

df["Churn Label"] = df["Churn Label"].map({"Yes":1,"No":0})
#Instantiate a Pipeline
pipeline = XPipeline()

# Add stages for specific features
pipeline.add_stages([
{"transformer": xtf.ChangeCases(
columns=['City', 'Gender', 'Senior Citizen', 'Partner', 'Dependents',
'Phone Service', 'Multiple Lines', 'Internet Service',
'Online Security', 'Online Backup', 'Device Protection', 'Tech Support',
'Streaming TV', 'Streaming Movies', 'Contract', 'Paperless Billing',
'Payment Method'], case="lower")},
{"feature":"City","transformer": xtf.Condense(pct=0.25)}, #-> Automatically condense extremely long tail values, to check if latent information
{"feature":"Monthly Charges", "transformer": xtf.SetDType(to_type="float")}, #-> Turn values into float
{"transformer": xtf.DropCols(
columns=['CustomerID', #-> Highly Cardinal,
"Total Charges", #-> Reduce Multicollinearity between Tenure and Monthly Costs
'Count', #-> Only one value
"Country", #-> Only one value
"State", #-> Only one value,
"Zip Code", #-> Highly Cardinal and Data Leakage if you keep City
"Lat Long", #-> Highly Cardinal
"Latitude", #-> Highly Cardinal
"Longitude", #-> Highly Cardinal
"Churn Value", #-> Data Leakage
"Churn Score", #-> Data Leakage
"CLTV", #-> Data Leakage
"Churn Reason", #-> Data Leakage
]
)},
])
Out:

<xplainable.preprocessing.pipeline.XPipeline at 0x29daaac50>

Preprocessed data

df_transformed = pipeline.fit_transform(df)
df_transformed.head()
CityGenderSenior CitizenPartnerDependentsTenure MonthsPhone ServiceMultiple LinesInternet ServiceOnline SecurityOnline BackupDevice ProtectionTech SupportStreaming TVStreaming MoviesContractPaperless BillingPayment MethodMonthly ChargesChurn Label
0los angelesmalenonono2yesnodslyesyesnonononomonth-to-monthyesmailed check53.851
1los angelesfemalenonoyes2yesnofiber opticnonononononomonth-to-monthyeselectronic check70.71
2los angelesfemalenonoyes8yesyesfiber opticnonoyesnoyesyesmonth-to-monthyeselectronic check99.651
3los angelesfemalenoyesyes28yesyesfiber opticnonoyesyesyesyesmonth-to-monthyeselectronic check104.81
4los angelesmalenonoyes49yesyesfiber opticnoyesyesnoyesyesmonth-to-monthyesbank transfer (automatic)103.71

Create Preprocessor to Persist to Xplainable Cloud

try:
preprocessor_id, version_id = client.preprocessing.create_preprocessor(
preprocessor_name="Telco Churn Preprocessing - v1.3.1",
preprocessor_description="Handling all preprocessing steps in the IBM Telco Churn Dataset",
pipeline=pipeline,
df=df
)
except XplainableAPIError as e:
print(f"Error creating preprocessor: {e}")
preprocessor_id, version_id = None, None

Loading the Preprocessor steps

Use the api to load pre-existing preprocessor steps from the xplainable cloud and transform data inplace.


pp_cloud = client.preprocessing.load_preprocessor(
version_id,
preprocessor_id
)

pp_cloud.stages
Out:

[{'feature': '__dataset__',

'name': 'ChangeCases',

'transformer': <xplainable.preprocessing.transformers.dataset.ChangeCases at 0x124c65840>},

{'feature': 'City',

'name': 'Condense',

'transformer': <xplainable.preprocessing.transformers.categorical.Condense at 0x111f1b5b0>},

{'feature': 'Monthly Charges',

'name': 'SetDType',

'transformer': <xplainable.preprocessing.transformers.mixed.SetDType at 0x111f18fa0>},

{'feature': '__dataset__',

'name': 'DropCols',

'transformer': <xplainable.preprocessing.transformers.dataset.DropCols at 0x29daa82e0>}]

if pp_cloud:
df_transformed_cloud = pp_cloud.transform(df)
else:
print("Using local preprocessing pipeline")
df_transformed_cloud = df_transformed.copy()

Create Train/Test split for model training validation

X, y = df_transformed.drop(columns=['Churn Label']), df['Churn Label']

X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.33, random_state=42)

2. Model Optimisation

The XParamOptimiser is utilised to fine-tune the hyperparameters of our model. This process searches for the optimal parameters that will yield the best model performance, balancing accuracy and computational efficiency.

opt = XParamOptimiser()
params = opt.optimise(X_train, y_train)
Out:

100%|██████████| 30/30 [00:02<00:00, 10.64trial/s, best loss: -0.8268936134101414]

3. Model Training

With the optimised parameters obtained, the XClassifier is trained on the dataset. This classifier undergoes a fitting process with the training data, ensuring that it learns the underlying patterns and can make accurate predictions.

model = XClassifier(**params)
model.fit(X_train, y_train)
Out:

<xplainable.core.ml.classification.XClassifier at 0x2a5c4f8e0>

4. Model Interpretability and Explainability

Following training, the model.explain() method is called to generate insights into the model's decision-making process. This step is crucial for understanding the factors that influence the model's predictions and ensuring that the model's behaviour is transparent and explainable.

model.explain()

The image displays two graphs related to a churn prediction model.

On the left is the 'Feature Importances' bar chart, which ranks the features by their ability to predict customer churn. 'Tenure Months' has the highest importance, confirming that the length of customer engagement is the most significant indicator of churn likelihood. 'Monthly Charges' and 'Contract' follow, suggesting that financial and contractual commitments are also influential in churn prediction.

The right graph is a 'Contributions' histogram, which quantifies the impact of a specific feature's values on the prediction outcome. The red bars indicate that higher values within the selected feature correspond to a decrease in the likelihood of churn, whereas the green bars show that lower values increase this likelihood.

The placement of 'Gender' at the bottom of the 'Feature Importances' chart conclusively indicates that the model does not consider gender a determinant in predicting churn, thereby ensuring the model's impartiality regarding gender.

5. Model Persisting

In this step, we first create a unique identifier for our churn prediction model using client.create_model_id. This identifier, shown as model_id, represents the newly instantiated model which predicts the likelihood of customers leaving within the next month. Following this, we generate a specific version of the model with client.create_model_version, passing in our training data. The output version_id represents this particular iteration of our model, allowing us to track and manage different versions systematically.

# Create a model
try:
model_id, version_id = client.models.create_model(
model=model,
model_name="Telco Churn Model - v1.3.1",
model_description="Predicting customers who are likely to leave the business within the next month.",
x=X_train,
y=y_train
)
except XplainableAPIError as e:
print(f"Error creating model: {e}")
model_id, version_id = None, None
Out:

0%| | 0/19 [00:00<?, ?it/s]

SaaS Models View

Model Image

SaaS Explainer View

Model Image

6. Model Deployment

The code block illustrates the deployment of our churn prediction model using the client.deployments.deploy function. The deployment process involves specifying the unique model_version_id that we obtained in the previous steps. This step effectively activates the model's endpoint, allowing it to receive and process prediction requests. The deployment response confirms the successful deployment with a deployment_id and other relevant information.

if model_id and version_id:
try:
deployment_response = client.deployments.deploy(
model_version_id=version_id #<- Use version id produced above
)
deployment_id = deployment_response.deployment_id
except XplainableAPIError as e:
print(f"Error deploying model: {e}")
deployment_id = None
else:
deployment_id = None

SaaS Deployment View

Model Image

Testing the Deployment programatically

This section demonstrates the steps taken to programmatically test a deployed model. These steps are essential for validating that the model's deployment is functional and ready to process incoming prediction requests.

  1. Activating the Deployment: The model deployment is activated using client.activate_deployment, which changes the deployment status to active, allowing it to accept prediction requests.
if deployment_id:
try:
client.deployments.activate_deployment(deployment_id=deployment_id)
except XplainableAPIError as e:
print(f"Error activating deployment: {e}")
else:
print("Deployment ID not available")
  1. Creating a Deployment Key: A deployment key is generated with client.generate_deploy_key. This key is required to authenticate and make secure requests to the deployed model.
if deployment_id:
try:
deploy_key = client.deployments.generate_deploy_key(
deployment_id=deployment_id,
description='API key for Telco Churn',
days_until_expiry=1
)
print(f"Deploy key created: {str(deploy_key)}")
except XplainableAPIError as e:
print(f"Error generating deploy key: {e}")
deploy_key = None
else:
deploy_key = None
Out:

Deploy key created: 342d630a-824b-4a90-bb51-6f328b3a4d63

  1. Generating Example Payload: An example payload for a deployment request is generated by client.generate_example_deployment_payload. This payload mimics the input data structure the model expects when making predictions.
#Set the option to highlight multiple ways of creating data
option = 2
if option == 1 and version_id:
try:
body = client.deployments.generate_example_deployment_payload(
model_version_id=version_id
)
except XplainableAPIError as e:
print(f"Error generating example payload: {e}")
body = []
else:
body = json.loads(df_transformed.drop(columns=["Churn Label"]).sample(1).to_json(orient="records"))
body[0]["Gender"] = None #<- Won't require this line the next release of xplainable
body
Out:

[{'City': 'other',

'Gender': None,

'Senior Citizen': 'no',

'Partner': 'no',

'Dependents': 'no',

'Tenure Months': 39,

'Phone Service': 'yes',

'Multiple Lines': 'no',

'Internet Service': 'no',

'Online Security': 'no internet service',

'Online Backup': 'no internet service',

'Device Protection': 'no internet service',

'Tech Support': 'no internet service',

'Streaming TV': 'no internet service',

'Streaming Movies': 'no internet service',

'Contract': 'two year',

'Paperless Billing': 'no',

'Payment Method': 'credit card (automatic)',

'Monthly Charges': 20.7}]

  1. Making a Prediction Request: A POST request is made to the model's prediction endpoint with the example payload. The model processes the input data and returns a prediction response, which includes the predicted class (e.g., 'No' for no churn) and the prediction probabilities for each class.
if deploy_key and body:
response = requests.post(
url="https://inference.xplainable.io/v1/predict",
headers={'api_key': str(deploy_key)},
json=body
)

value = response.json()
print("Prediction result:", value)
else:
print("Deploy key or body not available for prediction")
Out:

Prediction result: [{'index': 0, 'id': None, 'partition': '__dataset__', 'score': 0.11125574591149964, 'proba': 0.019052499656989675, 'pred': 0, 'support': 260, 'breakdown': [{'feature': 'base_value', 'value': None, 'score': 0.2602797795676134}, {'feature': 'City', 'value': 'other', 'score': -0.0004814338695100573}, {'feature': 'Gender', 'value': 'nan', 'score': 0.0}, {'feature': 'Senior Citizen', 'value': 'no', 'score': -0.002789401806391515}, {'feature': 'Partner', 'value': 'no', 'score': 0.022065879046674532}, {'feature': 'Dependents', 'value': 'no', 'score': 0.020121809618660676}, {'feature': 'Tenure Months', 'value': '39', 'score': -0.005027155608567363}, {'feature': 'Phone Service', 'value': 'yes', 'score': 0.0014792371139889873}, {'feature': 'Multiple Lines', 'value': 'no', 'score': -0.0014877658362602538}, {'feature': 'Internet Service', 'value': 'no', 'score': -0.017775137133722977}, {'feature': 'Online Security', 'value': 'no internet service', 'score': -0.017775137133722977}, {'feature': 'Online Backup', 'value': 'no internet service', 'score': -0.017775137133722977}, {'feature': 'Device Protection', 'value': 'no internet service', 'score': -0.017775137133722977}, {'feature': 'Tech Support', 'value': 'no internet service', 'score': -0.017775137133722977}, {'feature': 'Streaming TV', 'value': 'no internet service', 'score': -0.017775137133722977}, {'feature': 'Streaming Movies', 'value': 'no internet service', 'score': -0.017775137133722977}, {'feature': 'Contract', 'value': 'two year', 'score': -0.02257555571750508}, {'feature': 'Paperless Billing', 'value': 'no', 'score': -0.010341592396499698}, {'feature': 'Payment Method', 'value': 'credit card (automatic)', 'score': -0.011447431494387745}, {'feature': 'Monthly Charges', 'value': '20.7', 'score': -0.014114662770255377}]}]

SaaS Deployment Info

The SaaS application interface displayed above mirrors the operations performed programmatically in the earlier steps. It displays a dashboard for managing the 'Telco Customer Churn' model, facilitating a range of actions from deployment to testing, all within a user-friendly web interface. This makes it accessible even to non-technical users who prefer to manage model deployments and monitor performance through a graphical interface rather than code. Features like the deployment checklist, example payload, and prediction response are all integrated into the application, ensuring that users have full control and visibility over the deployment lifecycle and model interactions.

Model Image

Rendering AI-Generated Reports in Markdown

When working with AI-generated reports, readability is key. Instead of printing raw text, we can render the output directly as Markdown inside a Jupyter Notebook.

This allows us to use headings, lists, and other formatting styles, making the report much easier to consume and present.


report = client.gpt.generate_report(
model_id=model_id,
version_id=version_id,
target_description="Customer churn likelihood (1 = will churn, 0 = will stay)",
project_objective="Identify customers at risk of leaving to improve retention strategies",
max_features=10,
temperature=0.7
)

print(f"AI report generated!")
print(f"Report length: {len(report.report):,} characters")
Out:

AI report generated!

Report length: 6,198 characters

from IPython.display import Markdown, display

display(Markdown(report.body))